using System;
using System.Globalization;
using SG.Ling.AutoTranslator.Properties;

namespace SG.Ling.AutoTranslator.Translation
{
    public struct TranslationKey : IEquatable<TranslationKey>
    {
        public readonly string SourceText;
        public readonly int SourceLanguage;
        public readonly int TargetLanguage;

        public TranslationKey(string sourceText, int sourceLanguage, int targetLanguage)
        {
            if (sourceLanguage <= 0)
                throw new ArgumentOutOfRangeException("sourceLanguage", sourceLanguage, Resources.TranslationKey_TranslationKey_Not_a_valid_LCID_);
            if (targetLanguage <= 0)
                throw new ArgumentOutOfRangeException("targetLanguage", targetLanguage, Resources.TranslationKey_TranslationKey_Not_a_valid_LCID_);

            SourceText = sourceText;
            
            SourceLanguage = sourceLanguage;
            TargetLanguage = targetLanguage;
        }

        public TranslationKey(Tuple<string, CultureInfo, CultureInfo> tuple)
            : this(tuple.Item1, tuple.Item2, tuple.Item3)
        {
            // nothing to do
        }

        public TranslationKey(string sourceText, CultureInfo sourceLanguage, CultureInfo targetLanguage)
            : this(
                sourceText, sourceLanguage != null ? sourceLanguage.LCID : 0,
                targetLanguage != null ? targetLanguage.LCID : 0)
        {
            // nothing to do
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (obj.GetType() != typeof (TranslationKey)) return false;
            return Equals((TranslationKey) obj);
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(TranslationKey other)
        {
            return Equals(other.SourceText, SourceText) && other.SourceLanguage == SourceLanguage && other.TargetLanguage == TargetLanguage;
        }

        /// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
        /// <returns>
        /// A 32-bit signed integer that is the hash code for this instance.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override int GetHashCode()
        {
            unchecked
            {
                int result = SourceText.GetHashCode();
                result = (result*397) ^ SourceLanguage;
                result = (result*397) ^ TargetLanguage;
                return result;
            }
        }

        public static bool operator ==(TranslationKey left, TranslationKey right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(TranslationKey left, TranslationKey right)
        {
            return !left.Equals(right);
        }

        public Uri GetTranslateUri()
        {
            var sourceLanguage = CultureInfo.GetCultureInfo(SourceLanguage);
            var targetLanguage = CultureInfo.GetCultureInfo(TargetLanguage);

            var parameters = Uri.EscapeUriString(
    String.Format("?langpair={0}|{1}&text={2}&hl=en&ie=utf8&oe=utf8",
                  sourceLanguage.GetTwoLettercode("auto"),
                  targetLanguage.GetTwoLettercode("en"),
                  SourceText));
            return new Uri("http://translate.google.com/" + parameters);
        }
        

        public override string ToString()
        {
            return "tr:/" + SourceLanguage.ToString("X") + "/" + TargetLanguage.ToString("X") + "/" + SourceText;
        }
    }
}